package common_crypto

import (
	"crypto/aes"
	"encoding/base64"
	"math/big"
)

// Base62 字符集
const base62Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

// AesEncryptECB Aes加密
func AesEncryptECB(origDataStr, keyStr string) string {
	origData := []byte(origDataStr)
	key := []byte(keyStr)
	cipher, _ := aes.NewCipher(generateKey(key))
	length := (len(origData) + aes.BlockSize) / aes.BlockSize
	plain := make([]byte, length*aes.BlockSize)
	copy(plain, origData)
	pad := byte(len(plain) - len(origData))
	for i := len(origData); i < len(plain); i++ {
		plain[i] = pad
	}
	encrypted := make([]byte, len(plain))
	// 分组分块加密
	for bs, be := 0, cipher.BlockSize(); bs <= len(origData); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
		cipher.Encrypt(encrypted[bs:be], plain[bs:be])
	}
	return base64.StdEncoding.EncodeToString(encrypted)
}

// AesDecryptECB Aes解密
func AesDecryptECB(encryptedStr, keyStr string) string {
	defer func() {
		if err := recover(); err != nil {
		}
	}()
	encrypted, _ := base64.StdEncoding.DecodeString(encryptedStr)
	key := []byte(keyStr)
	cipher, _ := aes.NewCipher(generateKey(key))
	decrypted := make([]byte, len(encrypted))
	//
	for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
		cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
	}

	trim := 0
	if len(decrypted) > 0 {
		trim = len(decrypted) - int(decrypted[len(decrypted)-1])
	}

	return string(decrypted[:trim])
}

// EncodeToBase62 将字符串编码为 Base62 字符串
func EncodeToBase62(str string) string {
	// 将字符串转换为字节切片
	bytes := []byte(str)
	// 创建一个大整数并设置为字节切片表示的数值
	num := new(big.Int).SetBytes(bytes)

	// 用于存储 Base62 编码结果的切片
	var result []byte
	// 62 作为除数
	base := big.NewInt(62)
	// 用于临时存储取模结果
	mod := new(big.Int)

	// 当大整数不为 0 时，继续进行编码
	for num.Cmp(big.NewInt(0)) > 0 {
		// 取模运算，得到当前位的 Base62 索引
		num.DivMod(num, base, mod)
		// 根据索引从 Base62 字符集中取出对应的字符
		result = append([]byte{base62Chars[mod.Int64()]}, result...)
	}

	// 如果结果为空，说明输入的字符串为空，返回 0
	if len(result) == 0 {
		return "0"
	}

	return string(result)
}

// DecodeFromBase62 将 Base62 字符串解码为原始字符串
func DecodeFromBase62(encoded string) string {
	// 如果编码后的字符串是 "0"，则返回空字符串
	if encoded == "0" {
		return ""
	}

	// 62 作为基数
	base := big.NewInt(62)
	// 用于存储解码后的大整数
	num := new(big.Int)

	// 遍历编码后的字符串
	for _, char := range encoded {
		// 查找字符在 Base62 字符集中的索引
		var index int
		for i, c := range base62Chars {
			if c == char {
				index = i
				break
			}
		}
		// 将当前的大整数乘以 62 并加上当前字符的索引
		num.Mul(num, base).Add(num, big.NewInt(int64(index)))
	}

	// 将大整数转换为字节切片
	bytes := num.Bytes()
	// 将字节切片转换为字符串
	return string(bytes)
}

func generateKey(key []byte) (genKey []byte) {
	genKey = make([]byte, 32)
	copy(genKey, key)
	for i := 32; i < len(key); {
		for j := 0; j < 32 && i < len(key); j, i = j+1, i+1 {
			genKey[j] ^= key[i]
		}
	}
	return genKey
}
